home *** CD-ROM | disk | FTP | other *** search
Text File | 1986-05-24 | 5.6 KB | 207 lines | [TEXT/EDIT] |
- #Options Z
-
- // mod 9 30 85 tsh - decode only version for playing sound
- // mod 9 16 85 tsh - completely redo I/O buffering to be consistent with
- // previous SoundCap, make startup of compressed file work,
- // eliminate MAZlib:BufIO
- // MOD 09-01-85 MAZ - huffman variable-bit-width code
- // " - file compression routines created
-
- #include "MacCdefs.h"
- #include "MAZlib.h"
- #include "OSio.h"
- #include "pbDefs.h"
-
- // huffman compression of deltas, values
- #define type_value 0
- #define type_delta 1
-
- #asm
- include SysEquX.D
- include MacTraps.D
- #endasm
-
- // used in the file
- typedef struct
- {
- short int dict_leftson;
- short int dict_rightson;
- } dictent;
-
- // the dictionary packed - packed into on write, used during decode step
- dictent dictionary[511];
-
- // huffman total count
- long int huffcount;
-
- // IO packet
- ioParam huffIo;
-
- // open file, read the file header and decide allocation.
- // returns -1 if not compressed
- long int huffman_readsize(filename, refnum)
- char *filename;
- short refnum;
- {
- long lbuff[2];
-
- // open the input file
- huffIo.ioNamePtr = filename;
- huffIo.ioVRefNum = refnum; // default volume
- huffIo.ioVersNum = 0; // normal version
- huffIo.ioPermssn = 1; // reading
- huffIo.ioMisc = 0; // no buffer
- huffIo.ioResult = 1;
- PBOpen(&huffIo, false);
- if (huffIo.ioResult < 0)
- return(huffIo.ioResult);
- // read the header (2 long words)
- huffIo.ioBuffer = (char *)lbuff;
- huffIo.ioReqCount = 8; // 2 longwords
- huffIo.ioPosMode = 1; // absolute
- huffIo.ioPosOffset = 0; // from the beginning
- huffIo.ioResult = 1;
- PBRead(&huffIo, false);
- // read the compression field.
- if (lbuff[0] != 'HCOM')
- return(-1);
- huffcount = lbuff[1];
- return(huffcount);
- }
-
- huffman_close()
- {
- PBClose(&huffIo, false);
- }
-
- // read the huffman file and undo it into a flat sample buffer
- // after doing huffman_readsize()
- int huffman_input(bptr, psampling, iobuff, iocnt)
- unsigned char *bptr;
- long int *psampling;
- char *iobuff;
- long int iocnt;
- {
- unsigned char first_sample, *buffer, *p;
- short int dictsz;
- long int checksum, i, csum, count, type;
- long lbuff[4];
- char twoc[2];
-
- count = huffcount;
- buffer = bptr;
- // read in 14 bytes
- huffIo.ioBuffer = (char *)lbuff;
- huffIo.ioReqCount = 14; // 3 longwords, 1 word
- huffIo.ioPosMode = 0; // relative to mark
- PBRead(&huffIo, false);
- csum = lbuff[0]; // read the checksum
- type = lbuff[1]; // read the compression type (always delta)
- *psampling = lbuff[2]; // return the sampling rate
- // read the huffman dictionary up front into 'dictionary'
- dictsz = *(short *)(&lbuff[3]); // read dictionary size
- // read in the dictionary
- huffIo.ioBuffer = (char *)dictionary;
- huffIo.ioReqCount = sizeof(dictent)*dictsz; // size to read
- huffIo.ioPosMode = 0; // relative to mark
- PBRead(&huffIo, false);
- // preshift dictionary entries to speed processing
- for (i=0; i<511; i++)
- if (dictionary[i].dict_leftson >= 0)
- {
- dictionary[i].dict_leftson <<= 2;
- dictionary[i].dict_rightson <<= 2;
- }
- // read first sample in
- p = (unsigned char *)lbuff;
- huffIo.ioBuffer = (char *)p;
- huffIo.ioReqCount = 2; // 2 characters
- huffIo.ioPosMode = 0; // relative to mark
- PBRead(&huffIo, false);
- p++; // ignor pad byte twoc[0]
- first_sample = *p++;
- // process rest of buffer
- checksum = unhuff_buffer(buffer, count, first_sample, iobuff, iocnt);
- // test the checksum
- if (checksum != csum)
- return(-1);
- // checksum OK, read compressed readin
- return(0);
- }
-
- // huffman decode step (reads and decodes data)
- long int unhuff_buffer(buffer,count,first_sample,iobuffer,iocnt)
- unsigned char *buffer; // D0
- long int count; // D1
- unsigned char first_sample; // D2
- char *iobuffer; // D3
- long int iocnt; // D4
- {
- #asm
- iocnt EQU -4
- iobuff EQU -8
- stksiz EQU -12
-
- LINK A6,#stksiz
- MOVEM.L D1-D7/A0-A4,-(SP)
- MOVE.L D3,iobuff(A6) ;save I/O buffer
- MOVE.L D4,iocnt(A6) ;save I/O buffer size
- MOVE.L D0,A0 ; OUTPUT POINTER TO A0
- MOVE.B D2,(A0)+ ; OUTPUT FIRST SAMPLE
- SUBQ.L #1,D1 ; DECREMENT COUNT
- MOVE.L D1,D7 ; INTO R7
- MOVEQ #0,D0
- MOVE.L D0,A3 ; ZERO LONGWORD CHECKSUM
- ; POINT TO DICTIONARY ROOT - READY FOR PARSE
- LEA dictionary(A5),A2
- MOVEQ #0,D4 ; DICTIONARY CURRENT POINTER
- BRA.S BUFREAD ; jump into loop
-
- ; process a bit and branch further into Huffman tree
- BITLP: LSL.L #1,D5 ; SHIFT OVER 1 BIT
- BCC.S ZEROBIT ; BRANCH IF LEFT SON
- ADDQ.W #2,D4 ; POINT TO RIGHT SON
- ZEROBIT: MOVE.W 0(A2,D4.W),D4 ; LOAD SON
- MOVE.W 0(A2,D4.W),D0 ; CHECK FOR LEAF
- DBMI D3,BITLP
- BGE.S BUFWD ; TEST FOR BIT COUNTER EXPIRED
- ; at end of huffman encoding, sum the delta and output char
- ADD.W 2(A2,D4.W),D2 ; COMPUTE NEXT CHARACTER
- MOVE.B D2,(A0)+ ; OUTPUT NEXT SAMPLE
- ; prepare for next sample
- MOVEQ #0,D4 ; DICTIONARY CURRENT POINTER
- SUBQ.L #1,D7 ; DONE COLLECTING?
- BLE.S EOBLP
- TST.W D3
- BMI.S BUFWD
- ; loop to next bit
- BITCNT: DBF D3,BITLP ; NEXT BIT FROM INPUT
-
- ; GET ANOTHER LONG FROM THE INPUT BUFFER
- BUFWD: SUBQ.L #4,D6 ; we process 4 bytes at a time
- BGT.S BUFGO ; NO REFILL NEEDED
-
- ; READ ANOTHER BUFFER IN
- BUFREAD: MOVEM.L A0/D0-D2,-(SP) ;save ac's
- LEA huffIo(A5),A0 ;get our packet
- MOVEA.L iobuff(A6),A1 ;reset buffer ptr
- MOVE.L iocnt(A6),D6 ;reset buffer count
- MOVE.L A1,ioBuffer(A0) ;get buffer
- MOVE.L D6,ioReqCount(A0) ;get requested count
- CLR.W ioPosMode(A0) ;relative positioning
- _Read
- MOVEM.L (SP)+,A0/D0-D2 ;restore ac's
-
- BUFGO: MOVE.L (A1)+,D5
- ADD.L D5,A3 ; UPDATE CHECKSUM
- MOVEQ #31,D3 ; BITS IN LONG (-1 FOR DBF)
- BRA.S BITLP
-
- ; ALL DONE
- EOBLP: MOVE.L A3,D0 ; RETURN CHECKSUM
- MOVEM.L (SP)+,D1-D7/A0-A4
- UNLK A6
- RTS
- #endasm
- }
-